#ifndef _OBSERVER
#define _OBSERVER 1

#include <set>
#include "threading/mutex.h"

namespace FD
{
	namespace Kernel
	{
		/** CObserver base class for tracking when objects are unreferenced (their reference count goes to 0) and are being deleted.*/
		class FD_Kernel_Export CObserver
		{
		public:
			CObserver();
			virtual ~CObserver();

			/** objectDeleted is called when the observed object is about to be deleted.  The observer will be automatically
			* removed from the observed object's observer set so there is no need for the objectDeleted implementation
			* to call removeObserver() on the observed object. */
			virtual void objectDeleted(void*) {};
		};

		/** Class used by FD::Kernel::CReferenced to track the observers associated with it.*/
		class FD_Kernel_Export ObserverSet : public FD::Kernel::CReferenced
		{
		public:

			ObserverSet(const CReferenced* observedObject);

			CReferenced* getObserverdObject() { return _observedObject; }
			const CReferenced* getObserverdObject() const { return _observedObject; }

			/** "Lock" a CReferenced object i.e., protect it from being deleted
			*  by incrementing its reference count.
			*
			* returns null if object doesn't exist anymore. */
			CReferenced* addRefLock();

			inline FD::Kernel::Mutex* getObserverSetMutex() const { return &_mutex; }

			void addObserver(CObserver* observer);
			void removeObserver(CObserver* observer);

			void signalObjectDeleted(void* ptr);

			typedef std::set<CObserver*> Observers;
			Observers& getObservers() { return _observers; }
			const Observers& getObservers() const { return _observers; }

		protected:

			ObserverSet(const ObserverSet& rhs): FD::Kernel::CReferenced(rhs) {}
			ObserverSet& operator = (const ObserverSet& /*rhs*/) { return *this; }
			virtual ~ObserverSet();

			mutable FD::Kernel::Mutex      _mutex;
			CReferenced*                     _observedObject;
			Observers                       _observers;
		};
	}
}

#endif